/*  tBookShelf: TextPlugin
    (C) 2007  TvN (Volodymyr Tarasenko), e-mail: tvntsr@yahoo.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#ifndef TEXT_READER_TEXT_PLUGIN_HPP
#define TEXT_READER_TEXT_PLUGIN_HPP

#include <string>
#include <memory>
#include <stdexcept>

#include "LuaParser.hpp"
#include "PageManager.hpp"
#include "StreamManager.hpp"

#include "Utils/HyphenationManager.hpp"
#include "Utils/Fonts/FontManager.hpp"

struct BookMark
{
    size_t file_pos;
    size_t page_num;

};

// Main class for plugin implementation
class TextReader
{
public:
    TextReader()
        : mText(), 
          mStreamManager(0), 
          mFontManager(0), 
          mConfigParser(0), 
          mCacheManager(0), 
          mHyphenationManager(0),
          mPageOrientation(Portrait),
          mPageWidth(0),
          mPageHeight(0)
    {}

    ~TextReader()
    {
        if (mStreamManager)
            delete mStreamManager;

        if (mFontManager)
            delete mFontManager;

        if (mConfigParser)
            delete mConfigParser;
    }

    void registerStreamManager(std::auto_ptr<StreamManager>& sman)
    {
        if (mStreamManager)
            delete mStreamManager;

        mStreamManager = sman.release();
    }

    void registerFontManager(std::auto_ptr<FontManager>& fman)
    {
        if (mFontManager)
            delete mFontManager;

        mFontManager = fman.release();
    }

    void registerConfigManager(std::auto_ptr<ConfigParser>& cfg)
    {
        if (mConfigParser)
            delete mConfigParser;

        mConfigParser = cfg.release();
    }
    
    void registerCacheManager(std::auto_ptr<PageCacheManager>& cman)
    {
        if (mCacheManager)
            delete mCacheManager;

        mCacheManager = cman.release();
    }

    void registerHyphenationManager(std::auto_ptr<HyphenationManager>& hman)
    {
        if (mHyphenationManager)
            delete mHyphenationManager;

        mHyphenationManager = hman.release();
    }


    const std::string& textFileName() const
    {
        return mText;
    }

    StreamManager& streamManager()
    {
        if (mStreamManager == 0)
            throw std::runtime_error("StreamManager unregistered");

        return *mStreamManager;
    }

    const StreamManager& streamManager() const
    {
        if (mStreamManager == 0)
            throw std::runtime_error("StreamManager unregistered");

        return *mStreamManager;
    }

    ConfigParser& configManager()
    {
        if (mConfigParser == 0)
            throw std::runtime_error("ConfigParser unregistered");

        return *mConfigParser;
    }

    const ConfigParser& configManager() const
    {
        if (mConfigParser == 0)
            throw std::runtime_error("ConfigParser unregistered");

        return *mConfigParser;
    }

    FontManager& fontManager()
    {
        if (mFontManager == 0)
            throw std::runtime_error("FontManager unregistered");

        return *mFontManager;
    }

    const FontManager& fontManager() const
    {
        if (mFontManager == 0)
            throw std::runtime_error("FontManager unregistered");

        return *mFontManager;
    }

    PageCacheManager& cacheManager()
    {
        if (mCacheManager == 0)
            throw std::runtime_error("PageCacheManager unregistered");

        return *mCacheManager;
    }

    const PageCacheManager& cacheManager() const
    {
        if (mCacheManager == 0)
            throw std::runtime_error("PageCacheManager unregistered");
        
        return *mCacheManager;
    }

    HyphenationManager& hyphenationManager()
    {
        if (mHyphenationManager == 0)
            throw std::runtime_error("HyphenationManager unregistered");

        return *mHyphenationManager;
    }

    const HyphenationManager& hyphenationManager() const
    {
        if (mHyphenationManager == 0)
            throw std::runtime_error("Hyphenation unregistered");
        
        return *mHyphenationManager;
    }

    // Return page count
    int open(const std::string& file);

    void destroyPages()
    {
        cacheManager().destroyPages();
    }

    void preRenderPages(size_t   start, 
                        size_t   count);

    void renderPage(Page*        page, 
                    bool         imitate = false);

    void renderArea(Page*        page, 
                    char*        buff,
                    const Point& start,
                    const Point& end);

    void changeSpaces(std::string&       p, 
                      const TextStyle&   style);

    size_t getPageNumber(size_t          pos);
    
    void getPageText(const size_t        num,
                     const size_t        offset, 
                     std::string&        to,
                     const size_t        chars);


    void setPageOrientation(const PageOrientation& to);

    int getPageCount() const
    {
        return cacheManager().pageCount();
    }

    PageOrientation getPageOrientation()
    {
        return mPageOrientation;
    }
private:
    void copyPageBuffer(Page*, 
                        char* buff, 
                        const Point& start,
                        const Point& end);

    /// Reads strings while style is the same
    void readText(std::istream& from, 
                  std::string&  to, 
                  TextStyle&    style, 
                  size_t        max_chars = 4056);


    void rotatePageBuffer(Page* page);
private:
    // disable copying
    TextReader(const TextReader&);

    // disable assigments
    TextReader& operator=(const TextReader&);

private:
    std::string         mText;

    StreamManager*      mStreamManager;
    FontManager*        mFontManager;
    ConfigParser*       mConfigParser;
    PageCacheManager*   mCacheManager;
    HyphenationManager* mHyphenationManager;

    PageOrientation     mPageOrientation;

    size_t              mPageWidth;
    size_t              mPageHeight;
};


#endif //TEXT_READER_TEXT_PLUGIN_HPP
